require 'lib/test_input_generator'

class SearchController < ApplicationController
  include TestInputGenerator
  include EncodeToSQL
  
  before_filter :test_sentences_by_word_sequence,
                :except => :index
  before_filter :split_keywords_by_space,
                :except => [:index,:sentences_by_word_sequence,:list_by_word_sequence]
  before_filter :analyze_json_keywords,
                :only => [:sentences_by_word_sequence,:list_by_word_sequence]
  before_filter :prepare_variables,:except => :index
  before_filter :check_options,
                :only => [:list_by_strings,:list_by_words]
  before_filter :check_sequence_options, :only => :list_by_word_sequence
  before_filter :count_strings,
                :load_sentences_by_strings,
                :only => :sentences_by_strings
  before_filter :count_uniq_strings,
                :load_list_by_strings,
                :only => :list_by_strings
  before_filter :count_words,
                :load_sentences_by_words,
                :only => :sentences_by_words
  before_filter :count_uniq_words,
                :load_list_by_words,
                :only => :list_by_words
  before_filter :count_word_sequence,
                :load_sentences_by_word_sequence,
                :only => :sentences_by_word_sequence
  before_filter :count_uniq_word_sequence,
                :load_list_by_word_sequence,
                :only => :list_by_word_sequence

  # インターフェースを作る当面の間は検索トリガー
  def index
    redirect_to(:action => "sentences_by_word_sequence")
  end

  # 文字列を含んだ文章を検索する
  def sentences_by_strings
    data = Hash.new
    data["total"] = @pages.item_count
    data["sentences"] = @sentences.map{|sentence| 
      {"id" => sentence.id,
       "center" => sentence.center,
       "left_side" => sentence.left_side,
       "right_side" => sentence.right_side,
       "text" => sentence.text}
    }#TODO left right centerに分割
    respond_to do |format|
      format.js{ render_json data }
    end
  end
  
  # 文字列を含んだ単語リストを作成する
  # オプション：centerだけのuniqな単語リストを作れる
  def list_by_strings
    data = Hash.new
    data["total"] = @pages.item_count
    unless params[:center_uniq].blank?
      data["list"] = @list.map{|sentence| {"center" => sentence.center,"count" => sentence.count} }
    else
      data["list"] = @list.map{|sentence| 
        {"center" => sentence.center,
         "right_side" => sentence.right_side,
         "left_side" => sentence.left_side,
         "count" => sentence.count} 
      }
    end
    respond_to do |format|
      format.js{ render_json data }
    end
  end
  
  # 単語を含んだ文章を検索する
  def sentences_by_words
    data = Hash.new
    data["total"] = @pages.item_count
    data["sentences"] = @sentences.map{|sentence| 
      {"id" => sentence.id,
       "center" => sentence.center,
       "left_side" => sentence.left_side,
       "right_side" => sentence.right_side,
       "text" => sentence.text}
    }#TODO left right centerに分割
    respond_to do |format|
      format.js{ render_json data }
    end
  end
  
  # 任意の単語リストを作成する
  def list_by_words
    data = Hash.new
    data["total"] = @pages.item_count
    unless params[:center_uniq].blank?
      data["list"] = @list.map{|sentence| {"center" => sentence.center,"count" => sentence.count} }
    else
      data["list"] = @list.map{|sentence| 
        {"center" => sentence.center,
         "right_side" => sentence.right_side,
         "left_side" => sentence.left_side,
         "count" => sentence.count} 
      }
    end
    respond_to do |format|
      format.js{ render_json data }
    end
  end
  
  # 単語列を含んだ文章を検索する
  def sentences_by_word_sequence
    data = Hash.new
    data["total"] = @pages.item_count
    data["sentences"] = @sentences.map{|sentence| 
      {"id" => sentence.id,
       "center" => sentence.center,
       "left_side" => sentence.left_side,
       "right_side" => sentence.right_side,
       "text" => sentence.text}
    }#TODO left right centerに分割
    respond_to do |format|
      format.js{ render_json data }
    end
  end
  
  # 任意の単語列リストを作成する
  def list_by_word_sequence
    render :text => "test"
  end
  
  # 比較する二つの検索条件の上位n件を取得する
  def comparing_sequence
    # TODO
  end
  
  # 任意のsentence_idの周囲の文を取得する
  def around_sentences
    Corpus.find(:all,
      :conditions => {:id => (params[:id]-params[:range])..(params[:id]+params[:range])},
      :order => :id)
  end
  
  private
  def split_keywords_by_space
    @keywords = params[:keywords].split(Regexp.new('\s|　'))
  end

  def analyze_json_keywords
    @inputs = JsonParser.new.parse(params[:keywords])
  end
  
  def prepare_variables
    start = (params[:start] || 1).to_i
    @size = (params[:limit] || 20).to_i 
    @sort_col = (params[:sort] || 'id')# ここんとこを上手く
    @sort_dir = (params[:dir] || 'ASC')
    @per_page = ((start / @size).to_i) + 1
  end
  
  def check_options
    @center_uniq = params[:center_uniq] == "check"
    @group = @center_uniq ? "center" : "left_side,center,right_side"
    true # これ，いらないかも
  end
  
  def check_sequence_options
    @center_uniq = params[:center_uniq] == "check"
    @group = @center_uniq ? "center" : make_sequence_group(@inputs["keywords"].size)
    true # これ，いらないかも    
  end
  
  def count_strings
    @pages = Paginator.new(self,
      Corpus.count(:conditions => ["text ~ ?",@keywords.join('|')]), 
      @size, @per_page)
  end

  def load_sentences_by_strings
    @sentences = Corpus.find(:all,
      :select => "id, #{strings_select_sql(@keywords)},text,sequence,data",
      :conditions => ["text ~ ?",@keywords.join('|')],
      :limit => @pages.items_per_page,
      :offset=> @pages.current.offset, 
      :order => @sort_col+' '+@sort_dir)
  end

  def count_uniq_strings
    from_conditions = 
      "SELECT #{strings_select_sql(@keywords,@center_uniq)} FROM corpora WHERE (text ~ '#{@keywords.join('|')}') GROUP BY #{@group}"
    @pages = Paginator.new(self,
      Corpus.count_by_sql("SELECT count(*) AS count_all FROM (#{from_conditions}) AS target"), 
      @size, @per_page)
  end

  def load_list_by_strings# ソートに対応
    @list = Corpus.find(:all,
      :select => "#{strings_select_sql(@keywords,@center_uniq)},count(*)",
      :conditions => ["text ~ ?",@keywords.join('|')],
      :group => @group,
      :limit => @pages.items_per_page,
      :offset=> @pages.current.offset, 
      :order => 'count DESC')
  end

  def count_words # 一応良さそうだけどまだ怪しい
    @pages = Paginator.new(self,
      Corpus.count(:conditions => ["sequence ~ ?",to_word_regexp(@keywords)]), 
      @size, @per_page)
  end

  def load_sentences_by_words# インターフェースが出来たら，ちゃんとleftとrightが取れているか確認
    @sentences = Corpus.find(:all,
      :select => "id, #{word_select_sql(@keywords)},text,sequence,data",
      :conditions => ["sequence ~ ?",to_word_regexp(@keywords)],
      :limit => @pages.items_per_page,
      :offset=> @pages.current.offset, 
      :order => @sort_col+' '+@sort_dir)
  end

  def count_uniq_words# count_uniq_stringsとまとめられるけど，メンテナンスが逆にし辛くなるかも
    from_conditions = 
      "SELECT #{word_select_sql(@keywords,@center_uniq)} FROM corpora WHERE (sequence ~ '#{to_word_regexp(@keywords)}') GROUP BY #{@group}"
    @pages = Paginator.new(self,
      Corpus.count_by_sql("SELECT count(*) AS count_all FROM (#{from_conditions}) AS target"),
      @size, @per_page)
  end

  def load_list_by_words
    @list = Corpus.find(:all,
      :select => "#{word_select_sql(@keywords,@center_uniq)},count(*)",
      :conditions => ["sequence ~ ?",to_word_regexp(@keywords)],
      :group => @group,
      :limit => @pages.items_per_page,
      :offset=> @pages.current.offset, 
      :order => 'count DESC')
  end

  def count_word_sequence
    @pages = Paginator.new(self,
      Corpus.count(:conditions => ["data ~ ?",to_word_sequence_regexp(@inputs)]), 
      @size, @per_page)
  end
  
  def load_sentences_by_word_sequence
    @sentences = Corpus.find(:all,
      :select => "id, #{word_sequence_select_sql(@inputs)},text,sequence,data",
      :conditions => ["data ~ ?",to_word_sequence_regexp(@inputs)],
      :limit => @pages.items_per_page,
      :offset=> @pages.current.offset, 
      :order => @sort_col+' '+@sort_dir)
  end

  def count_uniq_word_sequence 
    from_conditions = 
      "SELECT #{uniq_word_sequence_select_sql(@inputs,@center_uniq)} FROM corpora WHERE (data ~ '#{to_word_sequence_regexp(@inputs)}') GROUP BY #{@group}"
    @pages = Paginator.new(self,
      Corpus.count_by_sql("SELECT count(*) AS count_all FROM (#{from_conditions}) AS target"),
      @size, @per_page)
  end
  
  def load_list_by_word_sequence
    @list = Corpus.find(:all,
      :select => "#{uniq_word_sequence_select_sql(@inputs,@center_uniq)},count(*)",
      :conditions => ["data ~ ?",to_word_sequence_regexp(@inputs)],
      :group => @group,
      :limit => @pages.items_per_page,
      :offset=> @pages.current.offset, 
      :order => 'count DESC')
  end

end
